import 'server-only';
import { getMessages as _getMessages, getTranslator } from 'next-intl/server';
import type zh from '@/messages/zh.json';

type Messages = typeof zh;

declare interface IntlMessages extends Messages {}

export type TTranslatedFields = Messages;

export type PrefixedTTranslatedFields<P extends keyof TTranslatedFields> =
  TTranslatedFields[P];

const _defaultLocale = 'zh';
const _defaultLocales = 'zh,en';

const dictionaries: Record<string, () => Promise<IntlMessages>> = {
  en: () => import(`@/messages/en.json`).then((module) => module.default),
  zh: () => import(`@/messages/zh.json`).then((module) => module.default),
};

const processTranslatedObjects = (
  t: any,
  prefix: string,
  obj: Record<string, any>,
) => {
  const result: Record<string, any> = {};
  for (const key of Object.keys(obj)) {
    const value = obj[key];
    if (typeof value === 'object') {
      result[key] = processTranslatedObjects(t, `${prefix}.${key}`, value);
    } else {
      const _value = `${prefix}.${key}`;
      result[key] = t(_value);
    }
  }
  return result;
};

export const getMessages = async (
  locale: string | undefined = _defaultLocale,
) => {
  try {
    const locales = (process.env.APP_LOCALES ?? _defaultLocales).split(',');
    let _locale = locale;
    if (!locales.includes(locale)) {
      _locale = process.env.APP_DEFAULT_LOCALE ?? _defaultLocale;
    }

    let _messages = await _getMessages(_locale);
    if (!_messages) {
      _messages = await dictionaries[_locale]();
    }

    return {
      locale: _locale,
      messages: _messages as IntlMessages,
      now: new Date(),
    };
  } catch (e) {
    const _locale = process.env.APP_DEFAULT_LOCALE ?? _defaultLocale;
    let _messages = await _getMessages(_locale);
    if (!_messages) {
      _messages = await dictionaries[_locale]();
    }

    return {
      locale: _locale,
      messages: _messages as IntlMessages,
      now: new Date(),
    };
  }
};

export const getTranslatedFields = async (
  locale: string,
  prefix: string,
  fields?: Record<string, any>,
): Promise<any> => {
  return processTranslatedObjects(
    await getTranslator(locale),
    prefix,
    fields ?? ((await getMessages(locale)).messages as any)[prefix],
  );
};
